let { config } = require('config.js')(runtime, this)
let singletonRequire = require('lib/SingletonRequirer.js')(runtime, this)
let commonFunctions = singletonRequire('CommonFunction')
let MyUtil = require('./utils.js')
let myutil = new MyUtil()

if (!auto.service) {
    toast('无障碍服务未启动！退出！')
    exit()
}
let storage = storages.create("jd_task");
let autoMute = storage.get('autoMute', false)
 
if (autoMute) {
    try {
        device.setMusicVolume(0)
        toast('成功设置媒体音量为0')
    } catch (err) {
        alert('首先需要开启权限，请开启后再次运行脚本')
        exit()
    }
}
let showConsole = function (show) {
    if (show) {
        console.show()
        sleep(500)
        console.setSize(device.width-100, 400)
    } else {
        console.hide()
    }
}

myutil.logInfo('开始完成京东任务...', config.qywx_bot)

let runningEngines = engines.all()
if (engines.myEngine().getSource().toString().indexOf('/jdmain.js') > -1 && runningEngines.length > 1) {
    device.setBrightnessMode(0)
    device.setBrightness(10)
    showConsole = function(a) {}
} else {
}
showConsole(1)
let _FloatyInstance = singletonRequire('FloatyUtil')
_FloatyInstance.enableLog()
myutil.setFloaty(_FloatyInstance)
myutil.logInfo('按音量下键停止', device.keepScreenDim(30 * 60 * 1000)) // 防止息屏30分钟
myutil.pushPlusToken = config.qywx_bot
 
// 自定义取消亮屏的退出方法
function quit() {
    myutil.sendNotifyMsg('任务进度通知', myutil.notifyMsg, config.qywx_bot)
    screenShotInNeight()
    device.cancelKeepingAwake()
    device.setBrightnessMode(1)
    showConsole(0)
    exit()
}
 
// 监听音量下键
function registerKey() {
    try {
        events.observeKey()
        events.observeToast()
    } catch (err) {
        myutil.logInfo('监听音量键停止失败，应该是无障碍权限出错，请关闭软件后台任务重新运行。')
        myutil.logInfo('如果还是不行可以重启手机尝试。')
        quit()
    }
    events.onKeyDown('volume_down', function (event) {
        myutil.logInfo('京东任务脚本停止了')
        myutil.logInfo('请手动切换回主页面')
        quit()
    })
    events.onToast(aToast => {
        myutil.onNotification(aToast)
    })
}
threads.start(registerKey)
 
function backToMain(pkg) {
    scrollUp()
    return myutil.backToText(/首页/, pkg)
}

function FreeFruit() {
    this.qiandao = 0
    this.getwater = 0
    this.friends = 0
    this.friendCount = 0
    this.nameQianDao = /8ff8554110b01c71.*|签到/
    this.nameGetWater = /f948ff17c79c25fa.*|领水滴/
    this.nameFriend = /228c5c13eaf85e98.*|好友/
    this.nameWaterOut = /86b551d1155595c3.*|浇水/
    this.pkgInId = 'jingdong'
    this.waterCount = 0

    this.taskQiandao = function() {
        if (this.qiandao) {
            return
        }
        if (!myutil.clickText(this.nameQianDao, /.*礼包/)) {
            if (!myutil.findTextDescMatchesTimeout(/.*签到.*/,2000)) {
                return false
            }
        } 
        if (myutil.clickText(/签到领.*|领取.*礼包/, 1000, undefined, undefined, true))
            myutil.clickText(/明日.*/, 1000, undefined, undefined, true)
        for (let ndx=0;ndx<3;++ndx) {
            this.closePopup()
            if (myutil.clickText(/关注得水滴/, 1000)) {
                sleep(5500)
                myutil.backToText(/免费水果|东东农场/, this.pkgInId)
                myutil.clickText(/去领取/, 5000)
                myutil.backToText(/免费水果|东东农场/, this.pkgInId)
                continue
            }
            break
        }
        myutil.backToText(this.nameQianDao, this.pkgInId)
        this.qiandao = 1
    }
    this.textFinder = function(button, lst) {
        let p = button.parent()
        p.parent().children().forEach(function(child) {
            if (child.text()) {
                if (lst.length < 2) {
                    lst.push(child.text())
                } else {
                    lst[1] = lst[1]+child.text()
                }
            }
        })
        myutil.logInfo(myutil.boundsInsideText(p.parent().bounds(), /.*/), lst, button.bounds())
    }
    this.textFinderFriend = function(button, lst) {
        button = button.parent().parent()
        if (button.indexInParent() > 2) {
            lst.push(button.parent().child(button.indexInParent()-2).text())
            lst.push(button.parent().child(button.indexInParent()-1).text())
        } else {
            let find = false
            button.parent().children().forEach(item => {
                if (find) {
                    return false
                }
                let rect1 = item.bounds()
                let rect2 = button.bounds()
                find = sameRect(rect1, rect2)
                if (find) {
                    return false
                }
                lst.push(item.text())
                return true
            })
            if (find) {
                while (lst.length > 2) {
                    lst.shift()
                }
            }
        }
    }   
    this.gotoJindou = function() {
        if(!myutil.clickText(/京东秒杀/, /再升级.*/)) return
        backToMain()
        myutil.clickText(/免费水果|东东农场/, /再浇.*/)
        myutil.clickText(/旧版/, /再浇.*/)
        myutil.clickText(this.nameGetWater, /领水滴/)
    }
    this.closeDialog = function(txt) {
        let key = 'water.dialog.close'
        let renwu = myutil.findTextDescMatchesTimeout(txt, 1000)
        if (!renwu) {
            let lst = myutil.storageOp(key, false)
            if (lst) {
                let x = lst[0]
                let y = lst[1]
                myutil.click(x,y, '关闭弹窗')
            }
            return false
        }
        renwu = renwu.parent()
        let p = renwu.parent()
        if (p.childCount() > 2) {
            myutil.logInfo('关闭弹窗')
            myutil.clickElement(p.child(p.childCount()-1))
            return true
        }
        let x = device.width - 40, y = renwu.bounds().centerY()
        myutil.storageOp(key, true, [x,y])
        myutil.click(x,y, '关闭弹窗')
        return true
    }
    this.剩余水量 = function() {
        let ele = myutil.findTextDescMatchesTimeout(this.nameWaterOut, 500)
        if (!ele) return
        let lst = myutil.boundsInsideElements(ele.bounds(), /\d+/)
        if (!lst || !lst[0]) {
            myutil.logInfo(lst)
            return
        }
        if (lst.length > 1) myutil.logInfo(lst)
        this.waterCount = Number.parseInt(lst[0].text())
        myutil.setFloatyInfoEle(lst[0], '水滴:'+lst[0].text())
    }
    this.taskWater = function() {
        this.剩余水量()
        if (this.getwater || !myutil.clickText(this.nameGetWater, /领水滴/)) {
            return
        }
        swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
        sleep(1000)
        swipe(device.width-100 + 20, device.height - 500, device.width-100, device.height - 200, 1000)
        sleep(1000)
        let lst = [/下单|水滴雨|万物商店|万人/]
        if (this.waterCount < 100) lst.push(/10次/)
        while (1) {
            this.closePopup()
            let [taskButton, taskText, taskCount, taskTitle] = 
                myutil.getTasksByText(/去完成|领取|去领取|去逛逛/, lst, this.textFinder)
            if (!taskButton) {
                break
            }
            if (taskTitle.indexOf('好友浇水') > 0 && taskButton.text().indexOf('领取') < 0) {
                this.friendCount = 2
                lst.push(/好友/)
                continue
            }
            myutil.clickElement(taskButton)
            if (taskButton.text().indexOf('领取') >= 0) {
                sleep(2000)                
            } else if (taskTitle.indexOf('免费水果') > 0) {
                sleep(5500) // 从首页重入
                return
            } else if (taskTitle.indexOf('(京东)?秒杀') > 0) {
                this.gotoJindou()
                sleep(2000)
            } else if (taskText.indexOf('浏览') >= 0) {
                r = taskText.match(/(\d+)[秒s]/)
                timeout = 2500
                if (r) {
                    timeout = parseInt(r[1]) * 1000 + 500
                }
                sleep(timeout)
            } else {
                myutil.logInfo(taskTitle, '重开任务列表')
            }
            myutil.backToText(/免费水果/, this.pkgInId)
            this.closeDialog(/领水滴|好\s*友/)
            sleep(1000)
            myutil.clickText(this.nameGetWater, /领水滴/)
            sleep(1000)
        }
        if (!this.closeDialog(/领水滴/)) {
            myutil.logInfo('没有找到任务列表的关闭按钮')
        }
        sleep(1000)
        this.getwater = 1
    }
    this.taskFriend = function() {
        if (this.friends) {
            return
        }
        this.剩余水量()
        if (this.waterCount < 20 || !myutil.clickText(this.nameFriend, /好\s*友/)) {
            this.friends = 1
            return
        }
        if (myutil.findTextDescMatchesTimeout(/.*还没有好友.*/,2000)) {            
            if (!this.closeDialog(/好\s友/)) {
                myutil.logInfo('没有找到好友列表的关闭按钮')
            }
            this.friends = 1
            return
        }
        let count = 1
        let white = [/豆豆/,/jd_WjohMbSkSEhV/]
        while (count && this.friendCount) {
            this.closePopup()
            let [taskButton, taskText, taskCount, taskTitle] = 
                myutil.getTasksByText(/26e11fbe52815a36.*|浇水/, [/邀请/], this.textFinderFriend, white)
            if (!taskButton) {
                if (white.length > 0) {
                    white = []
                    continue
                }
                break
            }
            myutil.clickElement(taskButton)
            sleep(2000)
            myutil.clickText(this.nameWaterOut, /好\s*友/)
            myutil.backToText(/好\s*友/, this.pkgInId)
            --this.friendCount
        }
        myutil.backToText(/好\s*友|再浇.*/, this.pkgInId)
        if (!this.closeDialog(/好\s*友/)) {
            myutil.logInfo('没有找到好友列表的关闭按钮')
        }
        sleep(1000)
        this.friends = 1
    }
    this.closePopup = function () {
        tm = 2000
        for (let i=0;i<3;++i) {
            if (myutil.clickText(/领取水滴|.*收下.*|去签到|去领取|回农场.*|.*回来/, tm)) {
                myutil.backToText(/免费水果|东东农场/, this.pkgInId)
            } else { break }
            tm = 1000
        }
    }
    this.点小鸭子 = function () {
        let ele = myutil.findTextDescMatchesTimeout(/连续点.*/, 2000)
        if (!ele) return
        let x = ele.bounds().centerX(), y = ele.bounds().centerY()
        count = 5
        while (count--) {
            click(x, y)
            sleep(1000)
        }
        myutil.click(x, y, '小鸭子')
        sleep(4500)
        this.closePopup()
    }
    this.种新水果 = function() {
        let ele = myutil.findTextDescMatchesTimeout(/先种下一棵.*/, 2000)
        if (!ele) {
            return
        }
        myutil.clickElement(ele)
        ele = myutil.findTextDescMatchesTimeout(/等级2/, 2000)
        myutil.clickElement(ele)
        ele = ele.parent().parent()
        if (!ele || ele.childCount() < 2) return
        ele = ele.child(ele.childCount()-2)
        myutil.clickElement(ele)
        sleep(2000)

    }
    this.main = function() {
        if (getStorageTimeSub(account+'.fruit') < 1000*3600) {
            return
        }
        myutil.appendNotifyMsg(`\n账号${account}种水果:\n`)
        ret = myutil.openAndInto(/免费水果|东东农场/, null, null, /.*?登录.*/)
        if (ret && ret.constructor === RegExp) {
            myutil.appendNotifyMsg(`\n未登录\n`)
            throw new Error('未登录')
        }
        this.ddnc()
        backToMain()
        取用户名和快递()
        storageOp(account+'.fruit', 1, (new Date()).getTime())
        return
        myutil.clickText(/旧版/, 3000)
        this.closePopup()
        if (myutil.clickText(/.*太火爆.*|再浇.*/, 10000)&&myutil.clickText(/.*太火爆.*/, 1000)) {
            let progress = myutil.findTextDescMatchesTimeout(/.*太火爆.*/, 1000)
            if (progress) {
                myutil.appendNotifyMsg(progress)
            }
            backToMain()
            取用户名和快递()
            return
        }
        let progress = myutil.findTextDescMatchesTimeout(/再浇.*/, 1000)
        if (progress) {
            myutil.appendNotifyMsg(progress)
        }
        this.closePopup()
        this.种新水果()
        let count = 0
        while ((!this.qiandao || !this.getwater || ! this.friends) && count < 5) {
            count++
            if (!myutil.findTextDescMatchesTimeout(/免费水果|东东农场/, 5000)) {
                myutil.openAndInto(/免费水果|东东农场/)
                sleep(2000)
                continue
            }
            this.taskQiandao()
            myutil.backToText(/再浇.*/, this.pkgInId)
            this.taskWater()
            myutil.backToText(/再浇.*/, this.pkgInId)
            this.taskFriend()
        }
        this.点小鸭子()
        if (getNumber(/(\d+)g/) > 150)
            myutil.clickText(this.nameWaterOut) // 浇水
        myutil.logInfo('免费水果结束')
        backToMain()
        取用户名和快递()
        storageOp(account+'.fruit', 1, (new Date()).getTime())
    }
    this.ddnc = function() {
        if (!myutil.findTextDescMatchesTimeout(/东东农场/, 3000)) {
            return
        }
        if (myutil.clickText(/.*太火爆.*|再浇.*/, 10000)&&myutil.clickText(/.*太火爆.*/, 1000)) {
            backToMain()
            return
        }
        myutil.closePopup(/买买买/, /\s*/, device.width/2, device.height/2)
        let mainMsg = /再浇.*/
        let rect = [0, device.height/2, device.width, device.height]
        let ele = myutil.findTextDescMatchesTimeout(mainMsg, 3000)
        if (ele) {
            myutil.appendNotifyMsg(ele)
            rect = {top:ele.bounds().bottom, left:0, bottom:device.height, right:device.width}
        }
        let eleLst = myutil.boundsInsideElements(rect, /(\d+g){1,2}/)
        let walter = 0
        if (eleLst && eleLst.length > 0) {
            walter = Number.parseInt(eleLst[0].text())
            let wcnt = 0
            let x = eleLst[0].bounds().centerX()
            let y = eleLst[0].bounds().centerY() - 60
            while (walter > 200 && wcnt < 30) {
                myutil.click(x, y, `walter${wcnt}`)
                sleep(1000)
                wcnt += 1
            }
        }
        myutil.logInfo('walter:', walter)
        let qiandao = {x: 108, y: ele.bounds().bottom+200}
        let task = {x: 482, y: ele.bounds().bottom+180}

        myutil.click(qiandao.x, qiandao.y, '签到')
        sleep(100)
        myutil.click(qiandao.x, qiandao.y, '签到2')
        myutil.closePopup(/买买买/, /\s*/, device.width/2, device.height/2)
        myutil.clickText(/点击签到.*|已连续.*/, 6000)
        myutil.clickText(/明(日|天).*/, 1000)
        myutil.backToText(mainMsg, this.pkgInId)

        myutil.click(task.x, task.y, '做任务')
        let doTask = /做任务 .*/
        myutil.clickText(doTask, 2000)
        let lst = [/下单|水滴雨|万物商店|万人|移动App/]
        let taskMgs = /去完成|领取|去领取|去逛逛|去浇水/
        if (walter < 100) {
            lst.push(/10次/)
            taskMgs = /去完成|领取|去领取|去逛逛/
        }
        let count = 3
        while (count) {
            let [taskButton, taskText, taskCount, taskTitle] = 
                myutil.getTasksByText(taskMgs, lst, undefined)
            if (!taskButton) {
                count--
                if (!myutil.clickText(doTask, 500)) {
                    myutil.click(task.x, task.y, '做任务')
                } else {
                    swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
                }
                sleep(1000)
                continue
            }
            if (taskButton.bounds().top > device.height) {
                swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
            }
            count = 3            
            r = taskText.match(/(\d+)[秒s]/)
            timeout = 6500
            if (r) {
                timeout = parseInt(r[1]) * 1000 + 500
            }
            myutil.clickElement(taskButton)
            myutil.closePopup(/买买买/, /\s*/, device.width/2, device.height/2)
            myutil.clickText(/开心收下.*/, 1000)
            if (taskButton.text().indexOf('去浇水') > -1) {
                sleep(3000)
                myutil.click(task.x, task.y, '做任务')
            } else {
                sleep(timeout)
                myutil.backToText(doTask, this.pkgInId)
            }
            sleep(1000)
        }
        myutil.closeDialog(doTask, null, null, 300)
    }
}

function nodeWalker(lstOrReg) {
    this.lstOrReg = lstOrReg
    this.find = false
    this.walk = function (node) {
        if (!node) return
        if (node.text()) {
            if ((this.lstOrReg instanceof Array))
            this.lstOrReg.push(node.text())
            else {
                if (node.text().match(lstOrReg)) {
                    this.find = myutil.clickElement(node, 2) || this.find
                }
            }
            return
        }
        node.children().forEach(item => {
            this.walk(item)
        })
    }
}

function JingDou() {
    this.tasks = 0
    this.pkgInId = 'jingdong'
    this.textFinder = function(button, lst) {
        let t = myutil.boundsInsideText(button.parent().bounds(), /.*/)
        lst.push(t)
    }
    this.gotoFruit = function() {
        if (myutil.clickText(/免费水果|东东农场/, /免费水果|东东农场/)) {
            sleep(2000)
            backToMain()
            myutil.clickText(/(京东)?秒杀/, /再升级.*/)
            return true
        }
        return false
    }
    this.关闭京豆任务列表 = function () {
        let ele = myutil.findTextDescMatchesTimeout(/规则/, 1000)
        let y = ele?ele.bounds().centerY():500        
        myutil.closeDialog(/.*等级.*/, null, null, y)
    }
    this.taskByOcr = function(jdRegx) {
        let title = myutil.getTitle()
        let ret = myutil.ocrImgInPath(/去完成/, sysScreenShot(true))
        sleep(5000)
        ret = ret && title != myutil.getTitle()
        if (ret) {
            myutil.backToText(jdRegx)
        }
        return ret
    }
    this.taskAction = function(jdRegx) {
        if (this.tasks) {
            return
        }
        showConsole(0)
        let regx = /连签\d+天/
        let regxInTaskWindow = /.*等级.*/
        let backRegx = /京豆可抵.*/
        let bt = 2
        let rect = [0, 70]
        this.tasks= myutil.clickText(regx, regxInTaskWindow, bt, rect)
        showConsole(1)
        let cnt=3
        let ocrChecked = false
        while (cnt&&this.tasks) {
            let [taskButton, taskText, taskCount, taskTitle] = myutil.getTasksByText(
                /去完成/, [/下单|收集水滴|浇水/], this.textFinder)
            if (!taskButton) {
                if (!ocrChecked && this.taskByOcr(regx)) {
                    continue
                }
                ocrChecked = true
                if (!myutil.findTextDescMatchesTimeout(jdRegx, 1000)) {
                    backToMain()
                    myutil.clickText(/首页/)
                    this.enterJinDou()
                }
                cnt--
                let renwu = myutil.findTextDescMatchesTimeout(regxInTaskWindow, 1000)
                if (!renwu) {
                    myutil.backToText(backRegx, this.pkgInId)
                    showConsole(0)
                    myutil.clickText(regx, regxInTaskWindow, bt, rect)
                    showConsole(1)
                }
                sleep(1000)
                continue
            }
            cnt=3
            myutil.clickElement(taskButton)
            if (taskTitle.match(/.*免费水果.*/)) {
                this.gotoFruit()
                sleep(1000)
                myutil.clickText(regx, /.*可额外得.*/, 3, [10, 10])
            } else if (taskText.indexOf('浏览') >= 0) {
                r = taskText.match(/(\d+)[秒s]/)
                timeout = 6500
                if (r) {
                    timeout = parseInt(r[1]) * 1000 + 500
                }
                sleep(timeout)
            }
            else {
                sleep(1500)
            }
            myutil.backToText(backRegx, this.pkgInId)
        }
        this.关闭京豆任务列表()
    }
    this.种豆textFinder = function(button, lst) {
        if (button.bounds().bottom - button.bounds().top < 20) {
            myutil.logInfo(button.text(), button.bounds())
            return lst
        }
        let walker = new nodeWalker(lst)
        walker.walk(button.parent().child(0))
        if (lst.length > 1) {
            button = lst.shift()
            let tmp = lst.join('')
            while (lst.length) {
                lst.shift()
            }
            lst.push(button)
            lst.push(tmp)
        }
    }
    this.关闭种豆任务列表 = function () {
        let loop = 3
        let regx = /完成任务越多.*/
        while (loop--) {
            let renwu = myutil.findTextDescMatchesTimeout(regx, 2000)
            if (!renwu) {
                myutil.logInfo('没有找到/完成任务越多.*/')
                return loop != 2
            }
            try {
                let cnt = renwu.parent().childCount()
                renwu = renwu.parent().child(cnt-1)
                if (myutil.clickElement(renwu, 2)) break
                sleep(2000)
            } catch (err) {
                myutil.logInfo('关闭任务列表失败', err)
            }
        }
        if (myutil.findTextDescMatchesTimeout(regx, 2000)) {
            myutil.closeDialog(regx)
        }
    }
    this.enter种豆得豆 = function(timeout) {
        let key = 'plant_bean'
        let x=0,y=0
        showConsole(0) 
        myutil.clickText(/赚京豆/, 1000, 2, [250, 0])
        showConsole(1)
        if (!myutil.clickText(/种豆得豆/, [10000,/更多任务/,10000])) {
            return false
        }
        {
            let dt = new Date()
            if (dt.getDay() == 1) {
                // 收上期
                // myutil.clickText(/上期/)
                if (myutil.clickText(/TZ4l9U.*/, 2000)) {
                    myutil.clickText(/收下京豆/)
                }
            }
        }
        myutil.clickText(/更多任务/, [3000, /.*任务越多.*/, 4000])
        return true
    }
    this.种豆得豆 = function () {
        this.enter种豆得豆(3000)
        swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
        sleep(2000)
        swipe(device.width-100 + 20, device.height - 500, device.width-100, device.height - 200, 1000)
        sleep(3500)
        let ele = myutil.boundsInsideElements([0,0, device.width, device.height*0.3], /.*成长值/)
        if (!ele.empty()) {
            myutil.appendNotifyMsg(ele[0].parent())
        }
        let loop = 5
        let backMsg = /.*任务越多.*|.*成长值/
        while (loop) {
            let [taskButton, taskText, taskCount, taskTitle] = myutil.getTasksByText(/去逛逛|去挑选|去关注|观看直播/, [], this.种豆textFinder)
            if (!taskButton) {
                let renwu = myutil.findTextDescMatchesTimeout(/.*任务越多.*/, 1000)
                if (!renwu) {
                    myutil.openAndInto(/(京东)?秒杀/)
                    this.enter种豆得豆(10000)
                    loop--
                    continue
                } else {                    
                    swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
                    loop--
                    sleep(1000)
                    continue
                }
            }
            loop = 5
            myutil.logInfo(taskButton.bounds())
            if (!myutil.clickElement(taskButton, 1)){
                sleep(1000)
                myutil.logInfo("点击失败")
            }
            if (myutil.findTextDescMatchesTimeout(taskTitle, 1000)||myutil.findTextDescMatchesTimeout(taskText,1000)) {
                myutil.clickElement(taskButton, 2)
            }
            myutil.clickText(/继续访问/, 3000)
            let timeout = 2500
            sleep(timeout)
            if (taskTitle.indexOf('免费水果') > -1) {
                if (myutil.clickText(/去完成/, 2000)) {
                    this.gotoFruit()
                    sleep(1000)
                    this.enter种豆得豆(10000)
                }
            }
            myutil.closeDialogByImage()
            if(!myutil.validBounds(taskButton)||myutil.clickText(/.*任务越多.*/)) {
                swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
                sleep(2000)
                continue
            }
            let a = taskTitle.indexOf('浏览店铺') > -1 || taskTitle.includes('关注店铺')
            let b = taskTitle.indexOf('关注频道') > -1
            let c = taskTitle.indexOf('关注商品') > -1
            let x = 0
            let y = 0
            let btnText = ''
            if (a|| b || c) {
                let txt = /进入并关注|去关注|进店并关注|ce1d9e1b3b30b86d|.*任务越多.*/
                let cnt = getCount(taskText)
                for (let i=0;i<cnt;++i) {
                    if (c) {
                        if (i==0) {
                            let reObj = getCount(taskText, 1)
                            let num = parseInt(reObj[0])
                            if (num != 0) {
                                for (let j=0;j<num;++j) {
                                    swipeLeftOrRight(true)
                                }
                                sleep(1000)
                            }
                            if (x==0 && y==0) {
                                reObj = myutil.findTextDescMatchesTimeout(txt, 2000)
                                if (!reObj) {
                                    myutil.clickText(txt, 2000)
                                } else {
                                    x = reObj.bounds().centerX()
                                    y = reObj.bounds().centerY()
                                    if (x <= 10 || x >= device.width) {
                                        x = device.width* 0.25
                                    }
                                    btnText = reObj.text()
                                    myutil.logInfo(x,y, reObj.bounds())
                                }
                            }
                        }
                        myutil.click(x, y, btnText)
                        sleep(1000)
                    } else {
                        myutil.setFloatyInfo({x: device.width/2, y: device.height/2}, txt)
                        myutil.clickText(txt, 2000)
                    }
                    myutil.backToText(txt)
                    if (c) {
                        myutil.logInfo('swipe')
                        swipeLeftOrRight(true)
                    }
                    sleep(1000)
                }
            }
            myutil.backToText(backMsg, this.pkgInId)
            if(!myutil.clickText(/.*任务越多.*/, 2000))
                myutil.clickText(/更多任务/, /.*任务越多.*/)
        }
        this.关闭种豆任务列表()
        sleep(1000)
        this.收取好友()
        myutil.backToText(backMsg, this.pkgInId)
        this.种豆收分()
        myutil.backToText(backMsg, this.pkgInId)
        ele = myutil.boundsInsideElements([0,0, device.width, device.height*0.3], /.*成长值/)
        if (!ele.empty()) {
            myutil.appendNotifyMsg(ele[0].parent())
        }
        return true
    }
    this.收取好友 = function() {
        swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 500, 1000)
        let loop = 0
        while (++loop < 10) {
            let ele = myutil.findOnec(/收取营养液/)
            if (!ele) {
                myutil.logInfo('找不到收取营养液')
                break
            }
            let parent = ele.parent().parent()
            let index = getIndexInParent(ele.parent())
            let imageLst = null
            for(let i = 0; i < parent.childCount(); i++){
                if (i == index) continue
                ele = parent.child(i)
                let lst = myutil.boundsInsideElements(ele.bounds(), /3/)
                let len = lst?lst.length:0
                myutil.logInfo(`${i} image count ${len}`, ele.bounds())
                myutil.setFloatyInfoEle(ele, `image count ${len}`)
                if (!lst) continue
                if (!imageLst || imageLst.length < lst.length) {
                    imageLst = lst
                }
            }
            let i = Math.floor(Math.random()*imageLst.length)
            if (!imageLst || !imageLst[i]) break
            myutil.logInfo('好友位置', imageLst[i].bounds())
            myutil.click(imageLst[i].bounds().centerX(), imageLst[i].bounds().centerY(), '好友位置')
            sleep(1000)
            myutil.clickText(/x\d/, 2000)
            sleep(1000)
            if (myutil.getNotification().indexOf('已达上限') > 0) break
        }
        if (loop != 1) myutil.backToText(/.*瓜分.*|更多任务/, this.pkgInId)
    }
    this.种豆收分 = function () {
        let cnt = 20
        let ele = myutil.findTextDescMatchesTimeout(/剩[\d\:]+|点击领取|.*7点.*/, 2000)
        if (ele) {
            let x = ele.bounds().centerX()
            let y = ele.bounds().centerY()
            myutil.click(x, y, 'X')
            myutil.clickText(/.*收下.*/, 1000)
            let x2 = x - 350
            let x3 = (x2 + x)/2
            let y3 = (y-90)
            while (myutil.findTextDescMatchesTimeout(/x\d+|.*7点.*/, 1000) && cnt--) {
                myutil.click(x2, y, 'X')
                myutil.click(x3, y3, 'X')
                myutil.clickText(/.*收下.*/, 1000)
            }
            return
        }
        cnt = 20
        for (let i=0;i<cnt;++i) {
            ele = myutil.findTextDescMatchesTimeout(/27308f124a7837c7|de22b56ee2f43e72|4644c5273796d972|0b62e8047bb7fa2e/, 2000)
            if (!ele) {
                while (myutil.clickText(/x\d+/, 2000) && cnt--) {
                    myutil.clickText(/.*收下.*/, 1000)
                }
                return
            }
            let p = ele.parent().parent().parent().parent()
            let walker = new nodeWalker(/x\d*/)
            walker.walk(p)
            if (!walker.find) {
                myutil.logInfo('收分结束', i)
                break
            }
            sleep(2000)
            let loop = 2
            while (myutil.clickText(/x\d+/, 1000) && loop--) { 
                myutil.clickText(/.*收下.*/, 1000)
            }
        }
    }
    this.enterJinDou = function() {        
        ret = myutil.openAndInto(/(京东)?秒杀|领领豆/, null, null, /.*?登录.*/)
        if (ret && ret.constructor === RegExp) {
            myutil.appendNotifyMsg(`\n未登录\n`)
            throw new Error('未登录')
            return
        }
        if (!myutil.openAndInto()) {
            myutil.clickText(/我的/, /签到领豆/)
            myutil.clickText(/签到领豆/, /(京东)?秒杀/)
        }
        myutil.findTextDescMatchesTimeout(/京豆可抵.*/,6000)
    }
    this.lldjd = function(msg) { // 浏览得京豆
        let backTxt =msg
        let ele = myutil.findTextDescMatchesTimeout(/浏览.*京豆.*/, 1000)
        if (!ele) {
            this.浏览得京豆加分()
            return
        }
        myutil.logInfo(ele.text())
        msg=/¥[\d\.]+/
        let taskButtons = textMatches(msg).find() || descMatches(msg).find()
        if (!taskButtons || taskButtons.length === 0) return
        let cnt = 0
        for (let i=0;i<taskButtons.length;++i) {
            ele = taskButtons[i]
            if (!ele) continue
            if (ele.bounds().bottom < device.height/2) continue
            if (ele.bounds().bottom > device.height) {
                swipe(device.width-100, device.height - 200, device.width-100 + 20, device.height - 600, 500)
            }
            cnt++
            myutil.clickElement(ele)
            sleep(2000)
            myutil.backToText(backTxt, this.pkgInId)
            if (cnt === 7) break
        }
        this.浏览得京豆加分()
    }
    this.浏览得京豆加分 = function() {
        let taskButtons = textMatches(/\+\d.*/).find()
        if (taskButtons.empty()) { // 如果找不到任务，直接返回
            myutil.logInfo('浏览得京豆加分:找不天+5')
            return
        }
        for (let i = 0; i < taskButtons.length; i++) {            
            if (taskButtons[i].bounds().bottom < device.height/2) {
                continue
            }
            myutil.clickElement(taskButtons[i])
            sleep(1000)
        }
    }
    this.main = function() {
        if (getStorageTimeSub(account+'.jingdou') < 1000*3600) {
            return
        }
        myutil.appendNotifyMsg(`\n领京豆账号${account}：\n`)
        this.enterJinDou()
        showConsole(0)
        myutil.clickText(/签到.*/, /.*签到提醒.*/)
        showConsole(1)
        let msg = /连签\d+天|京豆可抵/
        myutil.backToText(msg, this.pkgInId)
        let ele = myutil.findTextDescMatchesTimeout(/京豆可抵/,1000)
        if (ele) {
            myutil.appendNotifyMsg(ele.parent(), false)
        }
        this.种豆得豆()
        myutil.backToText(msg, this.pkgInId)
        this.taskAction(msg)
        myutil.backToText(msg, this.pkgInId)
        this.lldjd(msg)
        ele = myutil.findTextDescMatchesTimeout(/京豆可抵/,1000)
        if (ele) {
            myutil.appendNotifyMsg(ele.parent())
        }
        myutil.logInfo('领京豆结束')
        backToMain()
        storageOp(account+'.jingdou', 1, (new Date()).getTime())
    }
}

function getTimeout(txt, timeout) {
    r = txt.match(/(\d+)[秒s]/)
    timeout = timeout || 6500
    if (r) {
        timeout = parseInt(r[1]) * 1000 + 500
    }
    return timeout
}

function getCount(txt, notCount) {    
    let r = txt.match(/(\d+)\/(\d+)/)
    if (notCount) return r
    let cnt = 1
    if (r) {
        cnt = parseInt(r[2]) - parseInt(r[1])
    }
    return cnt
}

function sameRect(rect1, rect2) {
  return myutil.sameRect(rect1, rect2)
}

function getIndexInParent(button) {
    if (button.indexInParent() > -1) {
        return button.indexInParent()
    }
    for(let i = 0; i < button.parent().childCount(); i++){
        let child = button.parent().child(i);
        let rect1 = child.bounds()
        let rect2 = button.bounds()
        if (sameRect(rect1, rect2)) {
            return i
        }
    }
    return null
}

function 取用户名和快递() {
    if (!myutil.clickText(/我的/, /京豆/)) {
        return
    }
    let txt = myutil.getTitle()
    myutil.appendNotifyMsg(`用户信息:${txt}\n`)
    let ele = myutil.findTextDescMatchesTimeout(/待收货.*/, 1000)
    if (!ele) {
        return
    }
    txt = myutil.boundsInsideText(ele.parent().bounds(), /.*/)
    if (!txt.match(/\d+/)) {
        myutil.logInfo('没有待收货')
        myutil.clickText(/首页/, /秒杀/)
        return
    }
    myutil.clickText(/待收货.*/, /再次.*/)
    let eles = className('LinearLayout').idContains("com.jd.lib.ordercenter.feature").depth(15).find()
    eles.forEach(item => {
        if (item.childCount() === 4) {
            let txt = myutil.boundsInsideText(item.bounds(), /.*/)
            myutil.logInfo('待收货信息', txt)
            myutil.appendNotifyMsg(`快递信息:${txt}\n`)
        }
    })
    myutil.backToText(/购物车/ )
    myutil.clickText(/首页/, /秒杀/)
}


function getNumber(regx) {
    let ele = myutil.findTextDescMatchesTimeout(regx, 1000)
    if (!ele) return 0
    let m = ele.text().match(regx)
    return parseInt(m[1] || '0')
}
function storageOp(key, put, val) {
    if (put) {
        return storage.put(key, val)
    } 
    return storage.get(key, val)
}

function getStorageTimeSub(key) {
    let tm = new Date()
    let tm2 = parseInt(storage.get(key, 0))
    return (tm.getTime() - 0)
}

function swipeLeftOrRight(left) {
    if (left) {
        swipe(device.width-200, device.height/2-100, 200, device.height/2, 1000)
    } else {
        swipe(200, device.height/2, device.width-200, device.height/2-100, 1000)
    }
    sleep(2000)
}

function open多开(countNum, appName, testWd) {
    clearRecentApp()
    startAppInDesktop(eval('/'+appName+'/'))
    if (!myutil.findTextDescMatchesTimeout(testWd, 8000)) {    
        app.launchApp(appName)
        myutil.logInfo('多开界面打开失败', testWd)
        return false
    }
    if (appName.indexOf('BlackBox') > -1) {
        for (let j=0;j<countNum;++j) {
            swipeLeftOrRight(1)
            sleep(1000)
        }
        if (myutil.clickText(eval('/User ' + countNum + '/'))) {
            myutil.clickText(/取消/)
        }
    }
    return true
}

function switchAccount() {
    // let appName = '超级多开',pkg = 'com.polestar.super.clone'
    let appName = 'BlackBox64',pkg = 'top.niunaijun.blackboxa64'
    myutil.pkgName = pkg 
    appNames = ['BlackBox64', 'BlackBox32', '双开助手微信多开分身版']
    pkgs = ['top.niunaijun.blackboxa64', 'top.niunaijun.blackboxa32', 'com.excelliance.dualaid']
    let find = false
    for (let ndx in appNames) {
        appName = appNames[ndx]
        pkg = pkgs[ndx]
        if (app.getAppName(pkg) || app.getPackageName(appName)) {
            myutil.logInfo(app.getAppName(pkg), app.getPackageName(appName))
            myutil.pkgName = pkg
            find = true
            break
        }
    }
    if (!find) {
        myutil.logInfo('没有多开软件，结束')
        return
    }
    let subAppList = ['京东']
    for (let i=0;i<4;++i) {
        for (let ndx = 0; ndx < subAppList.length; ++ndx) {
            let name = subAppList[ndx]
            name = '/' + name + '\\s*' + (i+1) +'*/' 
            account = name
            if (getStorageTimeSub(account) < (1000*3600)) {
                myutil.logInfo(account, '最近跑过，跳过')
                continue
            }
            let obj = new WorkFlow()
            let needLoop = false
            let appOpened = false
            do {
                open多开(i, appName, /京东.*/)
                showConsole(0)
                appOpened = myutil.clickText(eval(name), 5000)
                myutil.clickText(eval(name), 2000)
                showConsole(1)
                if (!appOpened) {
                    myutil.logInfo('打开app失败', account) 
                    break
                }
                let ele = myutil.findTextDescMatchesTimeout(/购物车/, 20000)
                myutil.logInfo('打开了'+name, ndx)
                if (ndx == 0 && ele) {
                    myutil.clickText(/我的/)
                    sleep(3000)
                    myutil.clickText(/首页/)
                    myutil.clickText(/首页/)
                    needLoop = obj.main()
                }
            } while (needLoop)
        }
    }
}

function startAppInDesktop(name) {
    let left = true;
    swipeLeftOrRight(left)
    sleep(1000)
    for (let i=0;i<2;++i) {
        let ret = myutil.findTextDescMatchesTimeout(name, 2000)
        if (ret) {
            myutil.logInfo(ret.text(), ret.bounds())
            myutil.click(ret.bounds().centerX(), ret.bounds().centerY() - 360, '清理')
            sleep(3000)
            myutil.click(ret.bounds().centerX(), ret.bounds().centerY() - 70, ret.text())
            sleep(3000)
            break
        }
        swipeLeftOrRight(left)
    }
}

function screenShotInNeight() {
    let dt = new Date()
    if (dt.getHours() > 7) {
        return
    }
    sysScreenShot(false)
}

function sysScreenShot(hideConsole) {
    let f1 = [0, 1000, [device.width/2, 200], [device.width/2, 1600]]
    let f2 = [20, 1000, [device.width/2-150, 230], [device.width/2-150, 1630]]
    let f3 = [20, 1000, [device.width/2+150, 230], [device.width/2+150, 1630]]
    hideConsole? showConsole(0) : false
    gestures(f2, f1, f3)
    sleep(1000)
    hideConsole? showConsole(1) : false
    let path = files.join(files.cwd(), '/../DCIM/Screenshots')
    let lst = files.listDir(path, name => {
        return name.endsWith(".jpg") && files.isFile(files.join(path, name))
    })
    lst.sort()
    return files.join(path,lst[lst.length-1])
}

let canClear = device.model.indexOf('mi')
function clearRecentApp(all) {
    let killall = (all == undefined || all)
    if (killall) {
        home()
        sleep(1000)
    }
    if (!recents()) return
    sleep(2000)
    if (canClear) {
        canClear = myutil.clickText(/本机共有.*/, 2000) || (canClear == true)
        myutil.logInfo('canClear=',canClear, killall)
        if (canClear) {
            sleep(1500)
            back()
            sleep(1500)
            return
        }
    }
    if (killall)
    myutil.clickText(/全部清除/, 2000)
    back()
    sleep(1000)
    home()
    home()
    sleep(1500)
}

function dblBackQuitApp() {
    sleep(2000)
    backToMain()
    back()
    sleep(200)
    back()
    myutil.logInfo("已退出")
    sleep(1000)
}

function WorkFlow() {
    this.ndx = 0
    this.objList = [new FreeFruit(), new JingDou()]
    let dt = new Date()
    if (dt.getDate() === 14 && dt.getMonth() === 4 && dt.getFullYear() === 2024) {
        this.objList[0] = 0
    }
    this.main = function() {
        if (this.ndx == 0 && getStorageTimeSub(account) < (1000*3600)) {
            myutil.logInfo(account, '最近跑过，跳过')
            return false
        }
        let hasWork = this.ndx < this.objList.length
        if (hasWork) {
            try {
                this.objList[this.ndx++].main()
            } catch (err) {
                console.trace(err)
            }
        }
        hasWork = this.ndx < this.objList.length
        if (!hasWork) {
            tm = new Date()
            storage.put(account, tm.getTime())
            myutil.taskCount = {}
        }
        return hasWork
    }
}

function openRustDesk() {
    if (device.model != 'Redmi Note 4X') {
        return
    }
    pkg = 'com.carriez.flutter_hbb'
    myutil.openApp(pkg, /.*Rust.*/)
    myutil.clickText(/.*共享[\S\s]*/, 5000)
    if (!myutil.clickText(/启动服务/, 2000)) {
        return
    }
    myutil.clickText(/确认/, 2000)
    myutil.clickText(/立即开始.*/, 2000)
}

function 充电() {
    if (device.model != 'Redmi Note 4X') {
        return
    }
    let battery = device.getBattery()
    let isCharging = device.isCharging()
    myutil.logInfo('充电', battery, isCharging) 
    let act = ''
    if (isCharging) {
        if (battery > 90) {
            act = 'off'
        }
    } else {
        if (battery <= 25) {
            act = 'on'
        }
    }
    if (!act) return
    pkg = 'com.kankunit.smartplugcronus'
    myutil.openApp(pkg, /智能插座/)
    let i = 3
    while (i--) {
        myutil.clickText(/智能插座/, /定时任务/)
        if (myutil.clickText(/timer_mg/)) break
        let ele = id('device_btn').findOnce()
        if (ele) {
            myutil.logInfo('点击 device_btn')
            myutil.clickElement(ele)
            break
        }
    }
}

function findClose() {
    sleep(4000)
    img && img.recycle()
    img = images.load('https://gitee.com/makeavailable/VideoAudioManager/raw/master/auto_gui/autojs/resources/close1.png')
    let path = sysScreenShot(true)
    let img2 = images.read(path)
    let ret = images.findImage(img2, img, { threshold:0.1})
    if (!barHeight) {
        barHeight = getStatusBarHeightCompat()
    }
    if (ret) {
        ret.y = ret.y + 50
        ret.x = ret.x + 50
        myutil.click(ret.x, ret.y, 'X')
    }
    myutil.logInfo(ret, path, img.getWidth())
    img2.recycle()
    img.recycle()
    img = 0
    files.remove(path) 
}

function openTermux() {
    home()
    startAppInDesktop(/Termux/)
    home()    
}

function test() {
    // myutil.ocrImgInPath(/去完成/,sysScreenShot(true))
    let obj = new JingDou()
    obj.main()
    showConsole(0)
    quit()
}
 
let account = 'alone'
// 全局try catch，应对无法显示报错 
try {
    // test()
    if (device.model === 'Redmi Note 4X') {
        openRustDesk()
        充电()
        openTermux()
        throw new Error('stop')
    }
    myutil.openAndInto(/首页/, null, true)    
    let obj = new WorkFlow()
    while (obj.main()) {}
    clearRecentApp(true)
    switchAccount()
    myutil.logInfo('所有任务完成', '脚本结束运行！') 
    clearRecentApp()
    showConsole(0)
    quit()
} catch (err) {
    myutil.sendNotifyMsg('任务进度通知', myutil.notifyMsg, config.qywx_bot)
    device.cancelKeepingAwake()
    if (err.toString() != 'JavaException: com.stardust.autojs.runtime.exception.ScriptInterruptedException: null') {
        console.error(err)
    }
}
